/*
* at_list.c
*
*  Created on: 202211/7
*      Author: yanghx
*/


#include "at_parser.h"
#include "string.h"
#include "stdlib.h"
#include "at_list.h"
#include "wl_version.h"
#include "bsp_config.h"
#include "bsp.h"
#include "module_config.h"
#include "osal.h"

struct __CommStatus  stMonitor = {0};
uint8_t g_i2cGpioTest = 0;

#if defined (MODULE_INCLUDE_BMS)
extern BCT_BMSTypeDef BCT_BMSTest;
#endif

#if defined (MODULE_INCLUDE_SUBG)
SubBTestTypedef g_SubGTest;
emcTestTypedef g_emcTest;
static uint8_t g_sub_com_test = 0;
#endif

static uint32_t g_cpu_id_timestamp = 0;
static uint8_t g_cpu_id_flag = 0;

uint8_t get_fac_mode_en(void)
{
    return get_factory_status(FACTORY_TYPE_BOARDCHECK);
}

static int8_t param_search(char *param,char *result[],const int8_t result_len)
{
    int8_t index = 0;
    if(NULL == param)
    {
        return -1;
    }
    result[index]  = strtok(param, AT_SPLIT_STR);
    while(result[index])
    {
        index++;
        if(index >= result_len)
        {
            break;
        }
        else
        {
            result[index]  = strtok(NULL, AT_SPLIT_STR);
        }
    }
    return index;
}


/* test comand defined here */
int at_version(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,%.1f%%\r\n",AT_VERSION);
    
    return ERR_AT_NULL;
}

int enter_fac(uint32_t u32Port, char *param)
{
    if (get_factory_status(FACTORY_TYPE_FACCHECK) == 1 || get_ota_status() == 1 /* || gmowerData.powerOffState==1 */)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_MODE);
        return ERR_AT_INVALID_MODE;
    }

    set_factory_status(FACTORY_TYPE_BOARDCHECK, 1);
    at_rsp(u32Port, "OK%%\r\n");
    return ERR_AT_NULL;
}

int exit_fac(uint32_t u32Port, char *param)
{
#ifdef LIFT_MOTOR
    g_lift_motor_test = 0;
#endif

#if defined (MODULE_INCLUDE_SUBG) && defined (MODULE_INCLUDE_MOTOR)
    memset(&g_SubGTest, 0 , sizeof(SubBTestTypedef));
    memset(&board_check_data, 0 , sizeof(BoardCheckData_st));
    memset((uint8_t*)&mowerMotorControlDataForTest, 0, sizeof(mowerMotorControlDataForTest));
#endif
    set_factory_status(FACTORY_TYPE_BOARDCHECK, 0);
#if defined (MODULE_INCLUDE_ALARM)
    amAlarmSetMode(&gAlarm, AM_ALARM_MODE_NONE);
#endif
    at_rsp(u32Port, "OK%%\r\n");
    return ERR_AT_NULL;
}

int log_ctrl(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    g_logout_en = atoi(result[0]);
    at_rsp(u32Port, "OK,%d%%\r\n", g_logout_en);
    return ERR_AT_NULL;
}

int fw_ver_read(uint32_t u32Port, char *param)
{    
    at_rsp(u32Port, "OK,%04x%%\r\n", WL_SW_VERSION);
    return ERR_AT_NULL;
}

int boot_ver_read(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,%04x%%\r\n", getbootloaderversion());
    return ERR_AT_NULL;
}


int hardware_id_read(uint32_t u32Port, char *param)
{    
    at_rsp(u32Port, "OK,%d,%d%%\r\n", board_id_get(),board_num_get());
    return ERR_AT_NULL;
}

int dev_reset(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK%%\r\n");
    osal_delay_ms(500); //other operation?
    NVIC_SystemReset();
    return ERR_AT_NULL;
}

int dev_powerdown(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK%%\r\n");
    osal_delay_ms(1000); //other operation?
    power_ctrl(ECU_POWER_ON_MCU_EN,0);
    return ERR_AT_NULL;
}

int gpio_test(uint32_t u32Port, char *param)
{
    static GPIO_TypeDef * aGpioPort[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG};
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(3 != param_len && 4 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d,%d%%\r\n", ERR_AT_INVALID_PARAM,param_len);
        return ERR_AT_INVALID_PARAM;
    }
    char cmd = result[0][0];
    signed char port = result[1][0];
    uint8_t pin = atoi(result[2]);
    uint8_t pin_state = 0;
    port -= 'A';
    if (((cmd != 'R') && (cmd != 'W')) || 
        ((port < 0) || ((char)port >= sizeof(aGpioPort)/sizeof(GPIO_TypeDef *))) || 
        (pin > 15))
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
    
    if (cmd == 'W')
    {
        if(4 == param_len)
        {
            pin_state = atoi(result[3]);
            if(pin_state > 1)
            {
                at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
                return ERR_AT_PARAM_OVER_RANG;
            }
            else
            {
                bsp_gpio_write(aGpioPort[port],(1 << pin),pin_state);
            }
        }
        else
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
            return ERR_AT_INVALID_PARAM;
        }
    }
    pin_state = bsp_gpio_read(aGpioPort[port],(1 << pin));
    at_rsp(u32Port, "OK,%c,%c%d,%d%%\r\n", cmd, port+'A', pin, pin_state);
    return ERR_AT_NULL;
}

#if defined (MODULE_INCLUDE_SUBG)
int sub_test_en(uint32_t u32Port, char *param)
{
    g_SubGTest.test_mode = 1;
    g_SubGTest.subG_data = au8AtTxBuffer;
    at_rsp(u32Port, "OK%%\r\n");
    return ERR_AT_NULL;
}

void set_sub_com_test(uint8_t value)
{
    g_sub_com_test = value;
}

uint8_t get_sub_com_test(void)
{
    return g_sub_com_test;
}

int emc_test_enter(uint32_t u32Port, char *param)
{
    g_SubGTest.test_mode = 2;
    at_rsp(u32Port, "OK%%\r\n");
    return ERR_AT_NULL;
}

int EMC_TX_Test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(param_len != 2)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    
    g_emcTest.tx_mode = atoi(result[0]);
    g_emcTest.rx_mode = 0;
    g_emcTest.emc_channel = atoi(result[1]);
    
    at_rsp(u32Port, "OK %d ch%d\r\n",g_emcTest.tx_mode,g_emcTest.emc_channel);
    return ERR_AT_NULL;
}

int EMC_RX_Test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(param_len != 2)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    
    g_emcTest.rx_mode = atoi(result[0]);
    g_emcTest.tx_mode = 0;
    g_emcTest.emc_channel = atoi(result[1]);
    
    at_rsp(u32Port, "OK %d ch%d\r\n",g_emcTest.rx_mode,g_emcTest.emc_channel);
    return ERR_AT_NULL;

}

int sub_para_config(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(3 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    // if(0 == g_SubGTest.test_mode)
    // {
    //     at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_SUBG_INVALID_MODE);
    //     return ERR_AT_SUBG_INVALID_MODE;
    // }

    uint8_t power = atoi(result[0]);
    uint8_t channel = atoi(result[1]);
    int32_t id = atoi(result[2]);
    g_SubGTest.test_mode = 1;
    g_SubGTest.subG_update = 1;
    g_SubGTest.subG_power = power;
    g_SubGTest.subG_channel = channel;
    g_SubGTest.subG_id = id;
    at_rsp(u32Port, "OK,%d,%d,%d%%\r\n",power,channel,id);
    return ERR_AT_NULL;
}


int sub_test_tx(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    if(0 == g_SubGTest.test_mode)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_SUBG_INVALID_MODE);
        return ERR_AT_SUBG_INVALID_MODE;
    }

    uint8_t value = atoi(result[0]);
    g_SubGTest.subG_txrx = value;
    at_rsp(u32Port, "OK,%d%%\r\n",g_SubGTest.subG_txrx);
    return ERR_AT_NULL;
}

int sub_ret_val(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    if(0 == g_SubGTest.test_mode)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_SUBG_INVALID_MODE);
        return ERR_AT_SUBG_INVALID_MODE;
    }

    uint32_t u32Cmd = strtol(result[0], NULL, 10);
    if(u32Cmd < 3)
    {
        g_SubGTest.retMode = u32Cmd;
        if(u32Cmd == 0)
        {
            at_rsp(u32Port, "OK%%\r\n");
        }
        return ERR_AT_NULL;
    }
    else 
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
}

int sub_test_ext(uint32_t u32Port, char *param)
{
    if(0 == g_SubGTest.test_mode)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_SUBG_INVALID_MODE);
        return ERR_AT_SUBG_INVALID_MODE;
    }
    g_SubGTest.test_mode = 0;
    g_SubGTest.subG_txrx = 0;
    //need init for subg configure
    Si4463Init(g_SubGTxPower);
    g_SubGTest.subG_data = NULL;
    at_rsp(u32Port, "OK%%\r\n");
    return ERR_AT_NULL;
}

int sub_com_test(uint32_t u32Port, char *param)
{
    if(0 == g_SubGTest.test_mode)
    {
        at_rsp(u32Port, "ERROR, %d%%\r\n",ERR_AT_SUBG_INVALID_MODE);
        return ERR_AT_SUBG_INVALID_MODE;
    }
    g_sub_com_test_info.tx_cnt = 0;
    g_sub_com_test_info.rx_cnt = 0;
    g_SubGTest.subG_txrx = 0;
    set_sub_com_test(1);
    osal_delay_ms(2000);
    if(g_sub_com_test_info.tx_cnt != SUBG_COM_TEST_NUM)
    {
        at_rsp(u32Port, "ERROR, %d%%\r\n",ERR_AT_SUBG_TX);
        set_sub_com_test(0);
        return ERR_AT_SUBG_TX;
    }
    else if(g_sub_com_test_info.rx_cnt < SUBG_COM_TEST_NUM - 2)
    {
        at_rsp(u32Port, "ERROR, %d%%\r\n",ERR_AT_SUBG_RX);
        set_sub_com_test(0);
        return ERR_AT_SUBG_RX;
    }
    set_sub_com_test(0);
    float tx_rssi = 0;
    float rx_rssi = 0;
    for(uint8_t i = 0;i < g_sub_com_test_info.rx_cnt;i++)
    {
        tx_rssi += g_sub_com_test_info.tx_rssi[i];
        rx_rssi += g_sub_com_test_info.rx_rssi[i];
    }
    tx_rssi /= g_sub_com_test_info.rx_cnt;
    rx_rssi /= g_sub_com_test_info.rx_cnt;
    at_rsp(u32Port, "OK,%d,%d%%\r\n",(int16_t)tx_rssi,(int16_t)rx_rssi);
    return ERR_AT_NULL;
}

int sub_cfg_write(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t len = strlen(result[0]);
    if(len > COMM_PDA_ECU_SUBG_CFG_LEN)
    {
        at_rsp(u32Port, "ERROR,%d, %s%%\r\n", ERR_AT_PARAM_OVER_RANG, result[0]);
        return ERR_AT_PARAM_OVER_RANG;
    }
    uint8_t map_id = 0;
    for(map_id = 0;map_id < SUBG_BAND_TYPE_NUM;map_id++)
    {
        if(0 == memcmp(g_subg_map[map_id].name,result[0],4))
        {
            break;
        }
    }
    if(map_id == SUBG_BAND_TYPE_NUM)
    {
        at_rsp(u32Port, "ERROR,%d,%s%%\r\n", ERR_AT_PARAM_OVER_RANG,result[0]);
        return ERR_AT_PARAM_OVER_RANG;
    }
    // memcpy(gDataConfig.old_subgCfg,g_subg_map[map_id].name,COMM_PDA_ECU_SUBG_CFG_LEN);
    config_data_init();
    gDataConfig.subg_band = g_subg_map[map_id].band;
    int8_t ret = write_cfg_data(&gDataConfig);
    if(ret == FLASH_NORMAL)
    {
        ret = config_data_init();
        if(ret == FLASH_NORMAL)
        {
            Si4463Init(g_SubGTxPower);
            at_rsp(u32Port, "OK,s%d%%\r\n", gDataConfig.subg_band);
            return ERR_AT_NULL;
        }
        else
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_READ_FAILED);
            return ERR_AT_READ_FAILED;
        }
    }
    else
    {
        config_data_init();
        at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_WRITE_FAILED);
        return ERR_AT_WRITE_FAILED;
    }
}

// int sub_cfg_read(uint32_t u32Port, char *param)
// {
//     at_rsp(u32Port, "OK,s%d%%\r\n", gDataConfig.subg_band);
//     return ERR_AT_NULL;
// }

int subg_read(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,s%d,%d,%d,%d%%\r\n", gDataConfig.subg_band,
        g_SubGTest.subG_power,g_SubGTest.subG_channel,g_SubGTest.subG_id);
    return ERR_AT_NULL;
}

int subgPair(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t cmd = atoi(result[0]);
    if(cmd)
    {
        setSubGIntoPairStatus();
    }
    else 
    {
        setSubGExitPairStatus();
    }
    at_rsp(u32Port, "OK%%\r\n");
    return ERR_AT_NULL;
}

int subgDeletePairID(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t logic_id = atoi(result[0]);
    removeSubGPairInfo(logic_id);
    at_rsp(u32Port, "OK%%\r\n");
    return ERR_AT_NULL;
}

int sn_write(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t len = strlen(result[0]);
    if(len != (PN_LEN-2))
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }

    config_data_init();
    gDataConfig.pairinfo.master_pn[0] = 0x5A;
    gDataConfig.pairinfo.master_pn[1] = 0x59;
    memcpy((uint8_t*)&gDataConfig.pairinfo.master_pn[2], result[0], len);
    int8_t ret = write_cfg_data(&gDataConfig);
    if(ret == FLASH_NORMAL)
    {
        ret = config_data_init();
        if(ret == FLASH_NORMAL)
        {
            at_rsp(u32Port, "OK,%s%%\r\n", gDataConfig.pairinfo.master_pn);
            return ERR_AT_NULL;
        }
        else
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_READ_FAILED);
            return ERR_AT_READ_FAILED;
        }
    }
    else 
    {
        config_data_init();
        at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_WRITE_FAILED);
        return ERR_AT_WRITE_FAILED;
    }
}
#endif

int mem_read(uint32_t u32Port, char *param)
{
    #define MAX_DUMP_BYTES   (16)
    uint32_t au32Data[MAX_DUMP_BYTES>>2] = {0};
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t u32Addr = strtol(result[0], NULL, 16);
    memcpy(au32Data, (uint8_t*)u32Addr, MAX_DUMP_BYTES);
    at_rsp(u32Port, "ok,0x%08x:0x%08x,0x%08x,0x%08x,0x%08x%%\r\n",
           u32Addr, au32Data[0], au32Data[1], au32Data[2], au32Data[3]);
    return ERR_AT_NULL;
}

int mem_write(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(3 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t u32Addr = strtol(result[0], NULL, 16);
    uint32_t u32Data = strtol(result[1], NULL, 16);
    
    if (0 == strcmp(result[3], "xwx"))
    {
        *((uint32_t *)u32Addr) = u32Data;
        at_rsp(u32Port, "OK,0x%08x,0x%08x\r\n", u32Addr, u32Data);
        return ERR_AT_NULL; 
    }
    else
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
}

int log_level_set(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t loglevel = atoi(result[0]);
    if(loglevel < AM_LOG_LEVEL_MAX)
    {
        set_log_level(loglevel);
        at_rsp(u32Port, "OK, %d\r\n", get_log_level());
        return ERR_AT_NULL;
    }
    else
    {
       at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
       return ERR_AT_PARAM_OVER_RANG;
    }
}

int log_level_get(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,%d\r\n", get_log_level());
    return ERR_AT_NULL;
}

int module_log_level_set(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(2 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    // char *module = result[0];
    uint8_t loglevel = atoi(result[1]);
    if(loglevel  >= AM_LOG_LEVEL_MAX)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
    
#ifdef TCU_MODULE
    if(0 == memcmp(module,"TCU",3))
    {
        tcu_log_level_set(loglevel);
        at_rsp(u32Port, "OK,%d\r\n", tcu_log_level_get());
        return ERR_AT_NULL;
    }
    else
#endif

#if defined (MODULE_INCLUDE_BMS)
    if(0 == memcmp(module,"BMS",3))
    {
        bms_log_level_set(loglevel);
        at_rsp(u32Port, "OK,%d\r\n", bms_log_level_get());
        return ERR_AT_NULL;
    }
    else
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
#endif
    return ERR_AT_NULL;
}

int pn_write(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t len = strlen(result[0]);
    if(len != PN_LEN)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }

    factory_data_init();
    memcpy((uint8_t*)g_factory_nessary.pnArray, result[0], len);
    memset(&g_factory_nessary.pnArray[len],0,ECU_PN_MAX+1-len);
    int8_t ret = write_factory_data(&g_factory_nessary);
    if(ret == FLASH_NORMAL)
    {
        ret = factory_data_init();
        if(ret == FLASH_NORMAL)
        {
            at_rsp(u32Port, "OK,%s%%\r\n", g_factory_nessary.pnArray);
            return ERR_AT_NULL;
        }
        else
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_READ_FAILED);
            return ERR_AT_READ_FAILED;
        }
    }
    else 
    {
        factory_data_init();
        at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_WRITE_FAILED);
        return ERR_AT_WRITE_FAILED;
    }
}

int pn_read(uint32_t u32Port, char *param)
{   
    at_rsp(u32Port, "OK,%s%%\r\n", g_factory_nessary.pnArray);
    return ERR_AT_NULL;
}

#ifdef LIFT_MOTOR
int lift_motor_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(3 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t enable = atoi(result[0]);
    uint8_t forward = atoi(result[1]);
    uint8_t hight = atoi(result[2]);
    if(enable > 1 || forward > 1|| hight > LIFT_HIGHT_Max)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
    if(enable)
    {
        g_lift_motor_test_forward = forward;
        motorInterface.mowerMotorControlData.height = hight;
        
    }
    g_lift_motor_test = enable;
    at_rsp(u32Port, "OK,%d,%d,%d%%\r\n", g_lift_motor_test,g_lift_motor_test_forward, motorInterface.mowerMotorControlData.height);
    return ERR_AT_NULL;
}
#endif

#if defined (MODULE_INCLUDE_ALARM)
int buzzer_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    uint8_t mode = 0;

    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    mode = strtol(result[0], NULL, 10);
    if (mode == 0)
    {
        amAlarmSetMode(&gAlarm, AM_ALARM_MODE_NONE);
    }
    else
    {
        amAlarmSetMode(&gAlarm, AM_ALARM_MODE_FAC_CHECK);
    }

    at_rsp(u32Port, "OK%%\r\n");
    return ERR_AT_NULL;
}
#endif

#if defined (MODULE_INCLUDE_LIFTUP)
int hall_read(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,%d,%d%%\r\n", g_emergency_info.hw_state, LIFT_HALL_STATE());
    return ERR_AT_NULL;
}

int hall_read_value(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,%d,%d%%\r\n", g_emergency_info.hw_state, get_liftup_value());
    return ERR_AT_NULL;
}
#endif

#if defined (MODULE_INCLUDE_KEY)
int key_read(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,%d,%d,%d%%\r\n", 
        KEY_MOW_IRQ_READ(),
        KEY_PARK_IRQ_READ(),
        KEY_OK_IRQ_READ());
    return ERR_AT_NULL;
}
#endif

#ifdef TCU_MODULE
int tcu_com_test(uint32_t u32Port, char *param)
{
    char *test_str = "tcu_com_test\r\n";
    tcu_test_set(1);
    packData2Tcu((uint8_t*)test_str, strlen(test_str)+1, COMM_MOWER_TRIMMER_TEST, COMM_CMD_ACK_RD, ID_TCU,ID_SELF);
    osal_delay_ms(2000);
    if(0 == tcu_test_get())
    {
        at_rsp(u32Port, "OK%%\r\n");
        return ERR_AT_NULL;
    }
    else
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_TEST_FAILE);
        return ERR_AT_TEST_FAILE;
    }
}
#endif

int uart_up_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    board_check_data.comTest.enable = 1;
    board_check_data.comTest.result = 0;
    board_check_data.comTest.comType = atoi(result[0]);
    board_check_data.comTest.sendCnt = 6;
    board_check_data.comTest.ackCnt = 0;

    osal_delay_ms(1500);
    if(board_check_data.comTest.result == 1)
    {
        at_rsp(u32Port, "OK%%\r\n");
    }
    else 
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
    }
    return ERR_AT_NULL;
}

#if defined (MODULE_INCLUDE_BMS)
int get_cell_infor(uint32_t u32Port, char *param)
{
    if(g_u16BatErrorCode & BMS_ERROR_BAT_ARP)
    {
       at_rsp(u32Port, "ERROE,%d%%\r\n",ERR_AT_ECU_BAT_LINK);
       return ERR_AT_ECU_BAT_LINK;
    }
    at_rsp(u32Port, "OK,%.16s,%d%%\r\n",BMS_para_data.bat_Pn, Cell_Infor_Data.cell_type);
    return ERR_AT_NULL;
}

int get_bat_info(uint32_t u32Port, char *param)
{
    if(g_u16BatErrorCode & BMS_ERROR_BAT_ARP)
    {
       at_rsp(u32Port, "ERROE,%d%%\r\n",ERR_AT_ECU_BAT_LINK);
       return ERR_AT_ECU_BAT_LINK;
    }
    at_rsp(u32Port, "OK,%d,%d,%d,%d,%d,%d,%d%%\r\n",(s16)bmsGetData()->bat_data.TS1_Temperature,
        bmsGetSocValue(),bmsGetData()->bat_data.Stack_Voltage,bmsGetData()->bat_data.Pack_Current,
        Cell_Infor_Data.cell_parallel,bmsGetData()->board_i,bmsGetData()->board_v);
    return ERR_AT_NULL;
}

int charge_ctrl(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t u32Cmd = strtol(result[0], NULL, 10);
    BCT_BMSTest.TestFlag = u32Cmd;
    at_rsp(u32Port, "OK,%d%%\r\n",BCT_BMSTest.TestFlag);
    return ERR_AT_NULL;
}

int charge_i_pwm(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t u32Cmd = strtol(result[0], NULL, 10);
    BCT_BMSTest.pwmTest = u32Cmd;
    at_rsp(u32Port, "OK,%d%%\r\n",BCT_BMSTest.pwmTest);
    return ERR_AT_NULL;
}


int charge_v_pwm(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t u32Cmd = strtol(result[0], NULL, 10);
    BCT_BMSTest.volPwmTest = u32Cmd;
    at_rsp(u32Port, "OK,%d%%\r\n",BCT_BMSTest.volPwmTest);
    return ERR_AT_NULL;
}

int charge_cur_config(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t u32Cmd = strtol(result[0], NULL, 10);

    if(u32Cmd > 7000)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
    BCT_BMSTest.configCurrent = u32Cmd;
    at_rsp(u32Port, "OK,%d%%\r\n", u32Cmd);
    return ERR_AT_NULL;
}

int charge_vol_config(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t u32Cmd = strtol(result[0], NULL, 10);

    if(u32Cmd > 26000)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
    BCT_BMSTest.configVoltage = u32Cmd;
    at_rsp(u32Port, "OK,%d%%\r\n", u32Cmd);
    return ERR_AT_NULL;
}

int dc_in_ctrl(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t index = atoi(result[0]);
    switch(index)
    {
        case 0:
            DC_IN_CTL_CLOSE();
            break;
        case 1:
            DC_IN_CTL_OPEN();
            break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
    }
    at_rsp(u32Port, "OK,%d%%\r\n",index);
    return ERR_AT_NULL;   
}
#endif

#if defined (MODULE_INCLUDE_BMS) && defined (MODULE_INCLUDE_MOTOR)
int current_read(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t index = atoi(result[0]);
    int32_t value = 0;
    switch(index)
    {
        case CUR_ID_CHARGE:
            value = (int32_t)sensorData.adc_ops.readValue(ADC_CHARGER_I_MCU);
            break;
        //case CUR_ID_DISCHARGE:
        //    value = (int32_t)sensorData.adc_ops.readValue(ADC_DISCHARGE_I_MCU);
        //    break;
        case CUR_ID_LIFT_MOTOR:
            value = (int32_t)sensorData.adc_ops.readValue(ADC_LIFTING_CUR);
            break;
        case CUR_ID_VCU2:
            value = (int32_t)sensorData.adc_ops.readValue(ADC_BAT_MOTOR_CURRENT);
            break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
    }
    at_rsp(u32Port, "OK,%d%%\r\n",value);
    return ERR_AT_NULL;
}

int ntc_read(uint32_t u32Port, char *param)
{
   at_rsp(u32Port, "OK,%d,%d%%\r\n", (int16_t)sensorData.adc_ops.readValue(ADC_CHARGE_NTC), (int16_t)sensorData.adc_ops.readValue(ADC_LAWN_NTC));
   return ERR_AT_NULL;
}

int other_mcu_reset(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    if(strncmp(result[0], "VCU", 3) == 0)
    {
    #if 0
        /* if ecu sw  reset and vcu not reset, neead re-read flag.*/
        if (motorInterface.dev[MOTORDEV_VCU1].pwrOnReason == 0)
        {
            if (motorInterface_readPwronReason(MOTORDEV_VCU1) != 0)
            {
                at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_ECU_VCU_START);
                return ERR_AT_ECU_VCU_START;
            }
            osal_delay_ms(100);
        }

        if((motorInterface.dev[MOTORDEV_VCU1].pwrOnReason & START_STATUS) == 0)
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n",ERR_AT_ECU_VCU_START);
            return ERR_AT_ECU_VCU_START;
        }
        else
        {
            //am_gpioWritePin(VCU_RESET_PORT, VCU_RESET_PIN, 1);
            VCU1_RESET_WRITE(1);
            motorInterface.dev[MOTORDEV_VCU1].pwrOnReason &= ~START_STATUS;
            osal_delay_ms(5);
            //am_gpioWritePin(VCU_RESET_PORT, VCU_RESET_PIN, 0);
            VCU1_RESET_WRITE(0);
            osal_delay_ms(1000);
            if((motorInterface.dev[MOTORDEV_VCU1].pwrOnReason & START_STATUS) == 1)
            {
                at_rsp(u32Port, "OK%%\r\n");
                return ERR_AT_NULL;
            }
            else 
            {
                at_rsp(u32Port, "ERROR, %d%%\r\n", ERR_AT_ECU_VCU_RESET_FAILD);
                return ERR_AT_ECU_VCU_RESET_FAILD;
            }
        }    
#endif
    return ERR_AT_NULL;
    }
    else
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
}

int set_lift_motor_hight(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    motorInterface.mowerMotorControlData.height = atoi(result[0]);
    at_rsp(u32Port, "OK,%d%%\r\n", motorInterface.mowerMotorControlData.height);
    return ERR_AT_NULL;
}

int quality_test_mowing_motor(uint32_t u32Port, char *param)
{
#if 0    /* re-code on X4 */
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t test_mode = atoi(result[0]);
    BCT_Quality_Test_LawnMotor.retMode = test_mode;
    BCT_Quality_Test_LawnMotor.data = au8AtTxBuffer;
    at_rsp(u32Port, "OK,%d%%\r\n", BCT_Quality_Test_LawnMotor.retMode);
#endif
    return ERR_AT_NULL;
}
#endif

int get_other_at_version(uint32_t u32Port, char *param)
{
    // const char* str = "ATVER?%";
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    
    char board_char = result[0][0];
//    at_rsp(u32Port, "transfer to %c\r\n", board_char);
//    wl_delay(5);
    switch(board_char)
    {
    #ifdef TCU_MODULE
        case 'T':
            sendAtCmdToTrimmer((uint8_t*)str, strlen(str)+1, 0, COMM_CMD_CMAP_RD);
            return  ERR_AT_NULL;
            break;
    #endif
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_CMD);
            return  ERR_AT_INVALID_CMD;
    }
}

#ifdef TCU_MODULE
int tcu_ctrl_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(4 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    TcuCtrlInfo_st info;
    info.power = atoi(result[0]);
    info.mode = atoi(result[1]);
    info.speed = atoi(result[2]);
    info.func = atoi(result[3]);
    tcu_ctrl_update(&info);
    at_rsp(u32Port, "OK,%d,%d,%d,%d%%\r\n", info.mode,info.speed,info.power,info.func);
   
    return ERR_AT_NULL;
}

int fac_tcu_error_inject(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t inject = atoi(result[0]);
    tcu_set_error_inject(inject);
    at_rsp(u32Port, "OK,%d%%\r\n", inject);
    return ERR_AT_NULL;
}
#endif

#ifdef TCU_LINK_TEST_ENABLE
int fac_tcu_link_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t enable  = atoi(result[0]);
    if(enable > 1)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
    g_link_test.loss_cnt = 0;
    g_link_test.tx_cnt = 0;
    g_link_test.enable = enable;
    at_rsp(u32Port, "OK,%d%%\r\n", g_link_test.enable);
    return ERR_AT_NULL;
}
#endif


int cpu_id_read(uint32_t u32Port, char *param)
{
    BspCpuId_st *cpuid = bsp_cpu_id_read();
    uint16_t data[6] = {0};
    memcpy(data,cpuid,12);
    g_cpu_id_flag = 1;
    g_cpu_id_timestamp = getSystemTimestamp() & 0x00000000FFFFFFFF;
    at_rsp(u32Port, "OK,%04X%04X%04X%04X%04X%04X,%ld%%\r\n", 
        data[0],data[1],data[2],data[3],data[4],data[5],
        g_cpu_id_timestamp);
    return ERR_AT_NULL;
}


static int fac_info_read(uint32_t u32Port,uint8_t id)
{
    int ret = ERR_AT_NULL;
    FactoryDataNessary_st data;
    read_factory_data(&data);
    switch(id)
    {
        case DATA_ID_FAC_PN:
            at_rsp(u32Port, "OK,%s%%\r\n",data.pnArray);
        break;
        case DATA_ID_FAC_RANDOM:
            at_rsp(u32Port, "OK,%s%%\r\n",data.randomNumArray);
        break;
        case DATA_ID_FAC_KEY:
            at_rsp(u32Port, "OK,%s%%\r\n",data.iapKeyArray);
        break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            ret = ERR_AT_PARAM_OVER_RANG;
        break;
    }
    return ret;
}

#if defined (MODULE_INCLUDE_SUBG) && defined (MODULE_INCLUDE_SUBG)
static int config_info_read(uint32_t u32Port,uint8_t id,uint8_t slave_id)
{
    int ret = ERR_AT_NULL;
    dataConfigTypeDef data;
    char temp_str[DEVICE_CFG_PN_LEN+1] = {0};
    read_cfg_data(&data);
    switch(id)
    {
        case DATA_ID_CONFIG_SUBG_BAND:
            at_rsp(u32Port, "OK,s%d%%\r\n",data.subg_band);
        break;
        case DATA_ID_CONFIG_SUBG_BMS_PN:
            at_rsp(u32Port, "OK,%s%%\r\n",data.bmsPN);
        break;
        case DATA_ID_CONFIG_SUBG_NEXT_PAIR_ID:
            at_rsp(u32Port, "OK,%d%%\r\n",data.subg_next_pair_id);
        break;
        case DATA_ID_CONFIG_PAIR_BASE_INFO:
            memcpy(temp_str,data.pairinfo.master_pn,16);
            at_rsp(u32Port, "OK,%s,%d,%d%%\r\n",temp_str,data.pairinfo.self_device_id,data.pairinfo.paired_num);
        break;
        case DATA_ID_CONFIG_PAIR_SLAVE_INFO:
            if(0xff == slave_id)
            {
                at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
                ret = ERR_AT_INVALID_PARAM;
            }
            else if(slave_id >= SLAVE_DEVICE_NUM_MAX)
            {
                at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
                ret = ERR_AT_PARAM_OVER_RANG;
            }
            else
            {
                memcpy(temp_str,data.pairinfo.slave_pn[slave_id],16);
                at_rsp(u32Port, "OK,%d,%d,%d,%s%%\r\n",slave_id,data.pairinfo.slave_id[slave_id],data.pairinfo.slave_priority[slave_id],temp_str);
            }
        break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            ret = ERR_AT_PARAM_OVER_RANG;
        break;
    }
    return ret;
}
#endif

int flash_info_read(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len && 2 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t id = atoi(result[0]);
#if defined (MODULE_INCLUDE_SUBG)
    uint8_t slave_id = 0xff;
    if(2 == param_len)
    {
        slave_id = atoi(result[1]);
    }
#endif
    if(id < DATA_ID_FAC_MAX)
    {
        return fac_info_read(u32Port,id);
    }
#if defined (MODULE_INCLUDE_SUBG)
    else if(id >= DATA_ID_CONFIG_BASE && id < DATA_ID_CONFIG_MAX)
    {
        return config_info_read(u32Port,id,slave_id);
    }
#endif
    else
    {
        at_rsp(u32Port, "ERROR,%d,%d%%\r\n", ERR_AT_PARAM_OVER_RANG,id);
        return ERR_AT_PARAM_OVER_RANG;
    }
}

int sign_read(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,%s,%s,%s%%\r\n",g_factory_nessary.pnArray,
                g_factory_nessary.randomNumArray,g_factory_nessary.iapKeyArray);
    return ERR_AT_NULL;
}

int sign_write(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(4 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t check_num = atol(result[3]);
    check_num = check_num ^ 0xFFFFFFFF;
    if(g_cpu_id_flag)
    {
        g_cpu_id_flag = 0;
        uint8_t pn_len = strlen(result[0]);
        uint8_t random_len = strlen(result[1]);
        uint8_t key_len = strlen(result[2]);
        if(check_num != g_cpu_id_timestamp)
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_XOR_CHECK_FAILED);
            return ERR_AT_XOR_CHECK_FAILED;
        }
        else if( pn_len != PN_LEN || random_len != RANDOM_DATA_LEN || key_len != IAPKEY_LEN)
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
        }

        memcpy(g_factory_nessary.pnArray,result[0],pn_len);
        memset(&g_factory_nessary.pnArray[pn_len],0,ECU_PN_MAX+1-pn_len);
        memcpy(g_factory_nessary.randomNumArray,result[1],random_len);
        memset(&g_factory_nessary.randomNumArray[random_len],0,ECU_RANDOM_MAX+1-random_len);
        memcpy(g_factory_nessary.iapKeyArray,result[2],key_len);
        memset(&g_factory_nessary.iapKeyArray[key_len],0,ECU_IAP_MAX+1-key_len);
        if(write_factory_data(&g_factory_nessary))
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_WRITE_FAILED);
            return ERR_AT_WRITE_FAILED;
        }
        if(factory_data_init())
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_READ_FAILED);
            return ERR_AT_READ_FAILED;
        }
        at_rsp(u32Port, "OK,%s,%s,%s%%\r\n",g_factory_nessary.pnArray,
            g_factory_nessary.randomNumArray,g_factory_nessary.iapKeyArray);
        return ERR_AT_NULL;
    }
    else
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_SIGN_CONDITION);
        return ERR_AT_SIGN_CONDITION;
    }
}

#if defined (MODULE_INCLUDE_POWER)
int power_on_source_read(uint32_t u32Port, char *param)
{
    at_rsp(u32Port, "OK,%d%%\r\n",POWER_SOURCE_BY_PUSH());
    return ERR_AT_NULL;    
}

int power_switch(uint32_t u32Port, char *param)
{
    int ret = ERR_AT_NULL;
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(3 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    int power_switch_id = atoi(result[0]);
    int power_switch_value = atoi(result[1]); 
    uint8_t power_switch_time = atoi(result[2]);   //s
    if(power_switch_value >= 0 && power_switch_value <= 1)
    {
        if(0 == power_ctrl(power_switch_id,power_switch_value))
        {
            at_rsp(u32Port, "OK,%d,%d,%d%%\r\n", power_switch_id,power_switch_value,power_switch_time);
            ret = ERR_AT_NULL;
        }
        else
        {
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            ret = ERR_AT_PARAM_OVER_RANG;
        }
    }
    else
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        ret = ERR_AT_PARAM_OVER_RANG;
    }
    return ret;
}

int power_good_read(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t index = atoi(result[0]);
    uint32_t value = 0;
    switch(index)
    {
        case PG_ID_EDAGE_ALIGN:
            value = (int32_t)sensorData.adc_ops.readValue(ADC_BAT_MOTOR_PG);;
            break;
        // case PG_ID_LED_ARRAY:
        //     value = get_bat_led_array_pg_volt();
        //     break;

        case PG_ID_12V_DRIVER:
            value = POWER_GOOD_READ();
            break;

        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
    }            
    at_rsp(u32Port, "OK,%d%%\r\n",value);
    return ERR_AT_NULL;
}

int volt_read(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t index = atoi(result[0]);
    int32_t value = 0;
    switch(index)
    {
        case VOLT_ID_BAT:
            value = (int32_t)sensorData.adc_ops.readValue(ADC_BAT_VOLTAGE_FOR_CHARGING);
            break;
        case VOLT_ID_CHARGE_STU:
            value = (int32_t)sensorData.adc_ops.readValue(ADC_CHARGE_STU) ;
            break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
    }
    at_rsp(u32Port, "OK,%d%%\r\n",value);
    return ERR_AT_NULL;
}

int adc_volt_read(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(2 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t adc_index = atoi(result[0]);
    uint8_t adc_rank = atoi(result[1]);
    float adc_volt = 0;
    switch(adc_index)
    {
        case 3:
            if(adc_rank < ADC_CHANNEL_MAX)
            {
                adc_volt = sensorData.adc_ops.readValue(adc_rank);
                at_rsp(u32Port, "OK,%d%%\r\n",(uint32_t)adc_volt);
                return ERR_AT_NULL;
            }
            else
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
            break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;  
    }
}
#endif

#if defined (MODULE_INCLUDE_PINCTL)
int pin_read(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t index = atoi(result[0]);
    uint8_t value = 0;
    switch(index)
    {
    #ifdef TCU_MODULE
        case PIN_ID_EDGE_OVERCURRENT:         
            value = PAYLOAD_OVERCURRENT_READ();
            break;
    #endif
        case PIN_ID_CPU_TO_MCU_IO:
            value = ACU_CPU_TO_MCU_IO0_READ();
            break;
        case PIN_ID_MCU_TO_SOM_PWRON:
            value = ACU_SOM_PWRON_READ();
            break;
#ifdef TCU_MODULE
        case PIN_ID_EDGE_ALIGN_DETECT:
            value = PAYLOAD_DETECT_INSERT_READ();
            break;
#endif
        case PIN_ID_MOTOR_POWER_DISABLE:
            value = !POWER_OCD_READ();
            break;
        case PIN_ID_I2C_SCL:            
            value = BMS_I2C_SCL_READ();
            break;
        case PIN_ID_I2C_SDA:            
            value = BMS_I2C_SDA_READ();
            break;
        case PIN_ID_MOTOR_OVERCURRENT_DETECT:
            value = MOTOR_OCD_READ();
            break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
    }
    at_rsp(u32Port, "OK,%d%%\r\n",value);
    return ERR_AT_NULL;
}
uint8_t Bat_sw_en_flag = 0;
int pin_write(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(2 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t index = atoi(result[0]);
    uint8_t value = atoi(result[1]);
    if(value > 1)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }
    
    switch(index)
    {
        case PIN_ID_CPU_TO_MCU_IO:
            ACU_CPU_TO_MCU_IO0_WRITE(value);
            break;
        case PIN_ID_MCU_TO_SOM_PWRON:
            ACU_SOM_PWRON_WRITE(value);
            break;
        case PIN_ID_BAT_SW_EN:
            BMS_SW_EN_WRITE(value);
            if(value == 0)
            {
                Bat_sw_en_flag = 1;
            }
            else 
            {
                Bat_sw_en_flag = 0;
            }
            break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
    }
    at_rsp(u32Port, "OK,%d,%d%%\r\n",index,value);
    return ERR_AT_NULL;
}

int recover_ctrl(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t index = atoi(result[0]);
    switch(index)
    {
    #ifdef TCU_MODULE
        case RECOVER_ID_EDGE_OCD:
            PAYLOAD_OCD_RECOVER_WRITE(1);
            osal_delay_ms(1);
            PAYLOAD_OCD_RECOVER_WRITE(0);
            break;
    #endif
        case RECOVER_ID_MOTOR_POWER_RELEASE:
            POWER_OCD_RELEASE_WRITE(1);
            osal_delay_ms(1);
            POWER_OCD_RELEASE_WRITE(0);
            break;

        case RECOVER_ID_MOTOT_RELEASE:
            MOTOR_OCD_RELEASE_WRITE(1);
            osal_delay_ms(1);
            MOTOR_OCD_RELEASE_WRITE(0);
            break;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
    }
    at_rsp(u32Port, "OK,%d%%\r\n",index);
    return ERR_AT_NULL;
}

int i2cGPIOtest(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(2 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint8_t I2C_No = atoi(result[0]);
    uint8_t cmd = atoi(result[1]);

    switch (I2C_No)
    {
    case 1:
        g_i2cGpioTest = 1; 
        switch (cmd)
        {
        case 0:
            HAL_I2C_SDA_Test();
            BMS_I2C_SCL_WRITE(1);
            BMS_I2C_SDA_WRITE(0);
            at_rsp(u32Port, "OK%%\"\r\n");
            return ERR_AT_NULL;
        case 1:
            HAL_I2C_SDA_Test();
            BMS_I2C_SDA_WRITE(1);
            BMS_I2C_SCL_WRITE(0);
            at_rsp(u32Port, "OK%%\"\r\n");
            return ERR_AT_NULL;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
        }
    case 3:
        // MX_I2C1_Init();
        // g_i2cGpioTest = 0;
        g_i2cGpioTest = 1; 
        switch (cmd)
        {
        case 0:
            HAL_I2C_SDA_Test();
            DIS_I2C_SCL_WRITE(1);
            DIS_I2C_SDA_WRITE(0);
            at_rsp(u32Port, "OK%%\"\r\n");
            return ERR_AT_NULL;
        case 1:
            HAL_I2C_SDA_Test();
            DIS_I2C_SDA_WRITE(1);
            DIS_I2C_SCL_WRITE(0);
            at_rsp(u32Port, "OK%%\"\r\n");
            return ERR_AT_NULL;
        default:
            at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
            return ERR_AT_PARAM_OVER_RANG;
        }
        at_rsp(u32Port, "OK%%\"\r\n");
        return ERR_AT_NULL;
    default:
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }    
}

#if defined (MODULE_INCLUDE_SENSOR)
int rain_level_set(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint16_t level = atoi(result[0]);
    if(level <= ADC_VOLTAGE_REF)
    {
        rain.threshold = level;
        at_rsp(u32Port, "OK,%d%%\r\n", rain.threshold);
        return ERR_AT_NULL;
    }
    else
    {
       at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
       return ERR_AT_PARAM_OVER_RANG;
    }
}
#endif
#endif

#if defined (MODULE_INCLUDE_MOTOR)
int motor_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(4 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    mowerMotorControlDataForTest.cmdByModelSpeed.v = atoi(result[0]);
    mowerMotorControlDataForTest.cmdByModelSpeed.w = atoi(result[1]);
    mowerMotorControlDataForTest.cmdByModelSpeed.speed = atoi(result[2]);
    mowerMotorControlDataForTest.cmdByModelSpeed.height = atoi(result[3]);
    if (mowerMotorControlDataForTest.cmdByModelSpeed.v == 0 && mowerMotorControlDataForTest.cmdByModelSpeed.w == 0 && mowerMotorControlDataForTest.cmdByModelSpeed.speed == 0 && mowerMotorControlDataForTest.cmdByModelSpeed.height == 0)
    {
        mowerMotorControlDataForTest.cmdType = MOTOR_CONTROL_BY_MODEL;
    }
    else
    {
        mowerMotorControlDataForTest.cmdType = MOTOR_CONTROL_BY_SPEED_WITH_MODEL;
    }
    
    at_rsp(u32Port, "OK,%d,%d,%d,%d%%\r\n", mowerMotorControlDataForTest.cmdByModelSpeed.v, mowerMotorControlDataForTest.cmdByModelSpeed.w, mowerMotorControlDataForTest.cmdByModelSpeed.speed, mowerMotorControlDataForTest.cmdByModelSpeed.height);
    return ERR_AT_NULL;
}

int motor_direct_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(5 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    mowerMotorControlDataForTest.cmdByDirectSpeed.driverSpeed = atoi(result[0]); 
    mowerMotorControlDataForTest.cmdByDirectSpeed.turnAngle = atoi(result[1]);
    mowerMotorControlDataForTest.cmdByDirectSpeed.turnT = 1000;
    mowerMotorControlDataForTest.cmdByDirectSpeed.lawnSpeed = atoi(result[2]);
    mowerMotorControlDataForTest.cmdByDirectSpeed.liftHeight = atoi(result[3]);
    mowerMotorControlDataForTest.cmdByDirectSpeed.liftT = atoi(result[4]);
    if (mowerMotorControlDataForTest.cmdByDirectSpeed.driverSpeed == 0 && mowerMotorControlDataForTest.cmdByDirectSpeed.turnAngle == 0 && mowerMotorControlDataForTest.cmdByDirectSpeed.lawnSpeed == 0 && mowerMotorControlDataForTest.cmdByDirectSpeed.liftHeight == 0)
    {
        mowerMotorControlDataForTest.cmdType = MOTOR_CONTROL_BY_MODEL;
    }
    else
    {
        mowerMotorControlDataForTest.cmdType = MOTOR_CONTROL_BY_SPEED;
    }
    
    at_rsp(u32Port, "OK, driver[%d], turn[%d %d], NCU[%d], lift[%d %d]%%\r\n", mowerMotorControlDataForTest.cmdByDirectSpeed.driverSpeed, \
                                                                              mowerMotorControlDataForTest.cmdByDirectSpeed.turnAngle, mowerMotorControlDataForTest.cmdByDirectSpeed.turnT, \
                                                                              mowerMotorControlDataForTest.cmdByDirectSpeed.lawnSpeed, \
                                                                              mowerMotorControlDataForTest.cmdByDirectSpeed.liftHeight, mowerMotorControlDataForTest.cmdByDirectSpeed.liftT);
    return ERR_AT_NULL;
}

int motor_RPM_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);

    uint8_t motorIndex = 0;     /* MOTOR_MAX + lift */

    if(3 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    motorIndex = atoi(result[0]);
    if (motorIndex < MOTOR_MAX)
    {
        mowerMotorControlDataForTest.cmdByRPM.motorRPM[motorIndex] = atoi(result[1]);
        mowerMotorControlDataForTest.cmdByRPM.keepAliveEnable = atoi(result[2]);
    }
    else if (motorIndex == MOTOR_MAX)
    {
        mowerMotorControlDataForTest.cmdByRPM.liftPwmPulse = atoi(result[1]);
        mowerMotorControlDataForTest.cmdByRPM.keepAliveEnable = atoi(result[2]);
    }

    if (motorIndex == 0 && atoi(result[1]) == 0 && atoi(result[2]) == 0)
    {
        mowerMotorControlDataForTest.cmdType = MOTOR_CONTROL_BY_MODEL;
    }
    else
    {
        mowerMotorControlDataForTest.cmdType = MOTOR_CONTROL_BY_RPM;
    }
    
    at_rsp(u32Port, "OK, motor%d, %d,%d%%\r\n", atoi(result[0]), atoi(result[1]), atoi(result[2]));
    return ERR_AT_NULL;
}

int motor_read_status(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    uint8_t motorIndex = 0;     /* MOTOR_MAX + lift */
    motorDriverDataTypedef* motor;

    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    motorIndex = atoi(result[0]);
    motor = motorInterface_getMotorDriverHandle(motorIndex);
    if (motorIndex >= MOTOR_MAX || motor == NULL)
    {
        at_rsp(u32Port, "ERROR, %d >= %d %d%%\r\n", motorIndex, MOTOR_MAX, ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    
    at_rsp(u32Port, "OK, motor%d, %d,%d,%d,%d,%d,%d%%\r\n", \
        motorIndex, motor->status.Iq, motor->status.Spd, motor->status.Angle, motor->status.ticks, (int16_t)(motor->status.temp)-40, motor->status.faultCode.value);
    return ERR_AT_NULL;
}

int read_backmotor_assit_flag(uint32_t u32Port, char *param)
{
    UNUSED(param);
    at_rsp(u32Port, "OK, BackMotor: %#X%%\r\n", motorInterface_getBackMotorAssitFlag());
    return ERR_AT_NULL;
}

int get_motor_state(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(2 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    uint8_t type = atoi(result[0]);
    int16_t value[2] = {0};
    switch (type)
    {
    case MOTOR_NCU1:
        fct_check_lawnmotor_state(value, sizeof(value)/sizeof(int16_t));
        break;
    
    default:
        break;
    }
    
    at_rsp(u32Port, "OK,%d,%d%%\r\n", value[0], value[1]);
    return ERR_AT_NULL;
}

int imu_state_ret(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t u32Cmd = strtol(result[0], NULL, 10);
    if(u32Cmd > 2)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    } 

    if(0 == u32Cmd)
    {
        at_rsp(u32Port, "OK%%\r\n");
    }
    else if(u32Cmd == 1)
    {
        at_rsp(u32Port, "OK,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%%\n",\
            Imu.Sensor.swGyroX,\
            Imu.Sensor.swGyroY,\
            Imu.Sensor.swGyroZ,\
            Imu.Sensor.swAccelX,\
            Imu.Sensor.swAccelY,\
            Imu.Sensor.swAccelZ,\
            Imu.Sensor.swTemp, \
            Imu.Init.gyroOffset_x,\
            Imu.Init.gyroOffset_y,\
            Imu.Init.gyroOffset_z \
        );
    }
    return ERR_AT_NULL;
}
#endif

#if defined (MODULE_INCLUDE_ERRCODE)
int errorcode_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    amErrorSet(&gError, atoi(result[0]));

    at_rsp(u32Port, "OK %ld %%\r\n", atoi(result[0]));
    return ERR_AT_NULL;
}
#endif

#if defined (MODULE_INCLUDE_LED) || defined (MODULE_INCLUDE_SCREEN)
int display_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    uint8_t temp_param[PARAM_MAX_NUM] = {0};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(6 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }

    for(int i = 0;i < param_len;i++)
    {
        temp_param[i] = atoi(result[i]);
    }

    set_display_param(AT_CMD_TRIGGER, temp_param);

    return ERR_AT_NULL;
}

int rgb_led_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);

    if(1 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
#ifdef RGB_SELF_TEST
    g_rgb_test.single_flag = 1;
    g_rgb_test.color = atoi(result[0]);

    at_rsp(u32Port, "OK %d %%\r\n", g_rgb_test.color);
#else
    at_rsp(u32Port, "OK\r\n");
#endif
    return ERR_AT_NULL;
}
#endif

#ifdef BSP_FLASH_UNIT_TEST_EN
int factory_flash_test(uint32_t u32Port, char *param)
{
    char *result[PARAM_MAX_NUM] = {NULL};
    int8_t param_len = param_search(param,result,PARAM_MAX_NUM);
    if(2 != param_len)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_INVALID_PARAM);
        return ERR_AT_INVALID_PARAM;
    }
    uint32_t addr = atoi(result[0]);
    uint32_t len = atoi(result[1]);

    if(addr < APP_TEMP_B_START_ADDR)
    {
        at_rsp(u32Port, "ERROR,%d%%\r\n", ERR_AT_PARAM_OVER_RANG);
        return ERR_AT_PARAM_OVER_RANG;
    }

    bsp_flash_test(addr,len);
    return ERR_AT_NULL;
}
#endif

